package com.yfbao.horizon.schedule.tk.meter;


import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.stat.JdbcDataSourceStat;
import com.alibaba.druid.stat.JdbcStatementStat;
import com.alibaba.druid.util.Histogram;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.binder.MeterBinder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;

@Slf4j
@Component
public class DbPoolMetrics implements MeterBinder {

    @Autowired
    private DataSource dataSource;


    @Override
    public void bindTo(MeterRegistry meterRegistry) {
        if(dataSource instanceof DruidDataSource){
            log.info("db pool is druid");
            DruidDataSource druidDataSource = (DruidDataSource) this.dataSource;
            //最大活跃连接数峰值。
            druidDataSource.getActivePeak();
            //最大空闲连接数峰值
            druidDataSource.getPoolingPeak();

            String dbName ="default";

            DruidDataSource ds = druidDataSource;

            // 注册 Druid 连接池的指标
            //当前活跃的连接数
//            meterRegistry.gauge("druid.active.count", druidDataSource, DruidDataSource::getActiveCount);
//            //当前空闲的连接数
//            meterRegistry.gauge("druid.idle.count", druidDataSource, DruidDataSource::getPoolingCount);
//            //等待获取连接的线程数量
//            meterRegistry.gauge("druid.wait.count", druidDataSource, DruidDataSource::getWaitThreadCount);
//            //最大获取连接的线程数量
//            meterRegistry.gauge("druid.max.active", druidDataSource, DruidDataSource::getMaxActive);
//            //最大等待时长
//            meterRegistry.gauge("druid.max.wait", druidDataSource, DruidDataSource::getMaxWait);

            Gauge.builder("jdbc.connection.count", ds, DruidDataSource::getActiveCount).tag("state", "active").tag("datasource", dbName).description("Connection Active Count").register(meterRegistry);
            Gauge.builder("jdbc.connection.count", ds, DruidDataSource::getConnectCount).tag("state", "connect").tag("datasource", dbName).description(
                    "ConnectionConnectCount").register(meterRegistry);
            Gauge.builder("jdbc.connection.count", ds, DruidDataSource::getPoolingCount).tag("state", "pooling").tag("datasource", dbName).description("ConnectionPoolingCount").register(meterRegistry);
            Gauge.builder("jdbc.connection.count", ds, DruidDataSource::getCloseCount).tag("state", "close").tag("datasource", dbName).description("Connection Close Count").register(meterRegistry);
            Gauge.builder("jdbc.connection.count", ds, DruidDataSource::getDestroyCount).tag("state", "destroy").tag("datasource", dbName).description("ConnectionDestroyCount").register(meterRegistry);
            Gauge.builder("jdbc.connection.count", ds, DruidDataSource::getCommitCount).tag("state", "commit").tag("datasource", dbName).description("Connection Commit Count").register(meterRegistry);
            Gauge.builder("jdbc.connection.count", ds, DruidDataSource::getRollbackCount).tag("state", "rollback").tag("datasource", dbName).description("Connection Rollback Count").register(meterRegistry);
            Gauge.builder("jdbc.connection.count", ds, DruidDataSource::getConnectErrorCount).tag("state", "error").tag("datasource", dbName).description("Connection Connect Error Count").register(meterRegistry);
            JdbcDataSourceStat dataSourceStat = ds.getDataSourceStat();

            JdbcStatementStat statementStat = dataSourceStat.getStatementStat();

            Gauge.builder("jdbc.statement.count", statementStat, JdbcStatementStat::getCreateCount).tag("state", "create").tag("datasource", dbName).description("StatementCreateCount").register(meterRegistry);
            Gauge.builder("jdbc.statement.count", statementStat, JdbcStatementStat::getPrepareCount).tag("state", "prepare").tag("datasource", dbName).description("StatementPrepareCount").register(meterRegistry);
            Gauge.builder("jdbc.statement.count", statementStat, JdbcStatementStat::getExecuteCount).tag("state", "execute").tag("datasource", dbName).description("StatementExecuteCount").register(meterRegistry);
            Gauge.builder("jdbc.statement.count", statementStat, JdbcStatementStat::getRunningCount).tag("state", "running").tag("datasource", dbName).description("StatementRunningCount").register(meterRegistry);
            Gauge.builder("jdbc.statement.count", statementStat, JdbcStatementStat::getCloseCount).tag("state", "close").tag("datasource", dbName).description("StatementCloseCount").register(meterRegistry);
            Gauge.builder("jdbc.statement.count", statementStat, JdbcStatementStat::getErrorCount).tag("state", "error").tag("datasource", dbName).description("StatementErrorCount").register(meterRegistry);

            Gauge.builder("jdbc.lock.queue.length", ds, DruidDataSource::getLockQueueLength).tag("datasource", dbName).description("LockQueueLength").register(meterRegistry);
            Gauge.builder("jdbc.wait.thread.count", ds, DruidDataSource::getNotEmptyWaitThreadCount).tag("datasource", dbName).description("WaitThreadCount").register(meterRegistry);

            Gauge.builder("jdbc.execute.query.count", ds, DruidDataSource::getExecuteQueryCount).tag("mode", "query").tag("datasource", dbName).description("ExecuteQueryCount").register(meterRegistry);
            Gauge.builder("jdbc.execute.update.count", ds, DruidDataSource::getExecuteUpdateCount).tag("mode", "update").tag("datasource", dbName).description("ExecuteUpdateCount").register(meterRegistry);


            Gauge.builder("druid.datasource.activeCount", druidDataSource, DruidDataSource::getActiveCount)
                    .description("当前活跃的连接数")
                    .register(meterRegistry);

            Gauge.builder("druid.datasource.poolingCount", druidDataSource, DruidDataSource::getPoolingCount)
                    .description("当前空闲的连接数")
                    .register(meterRegistry);

            Gauge.builder("druid.datasource.connectCount", druidDataSource, DruidDataSource::getConnectCount)
                    .description("累计获取的连接数")
                    .register(meterRegistry);

            Gauge.builder("druid.datasource.closeCount", druidDataSource, DruidDataSource::getCloseCount)
                    .description("关闭连接的次数")
                    .register(meterRegistry);

            Gauge.builder("druid.datasource.waitingCount", druidDataSource, DruidDataSource::getWaitThreadCount)
                    .description("等待获取连接的线程数量")
                    .register(meterRegistry);
            Histogram transactionHistogram1 = druidDataSource.getTransactionHistogram();
//            transactionHistogram.getSum()
            long[] transactionHistogram = transactionHistogram1.getRanges();
            // 暴露每个时间段的事务数量
            Gauge.builder("druid.transactions.0_1ms", () -> transactionHistogram[0])
                    .description("事务执行耗时在0-1ms至间的数量")
                    .register(meterRegistry);

            Gauge.builder("druid.transactions.1_10ms", () -> transactionHistogram[1])
                    .description("事务执行耗时在1-10ms至间的数量")
                    .register(meterRegistry);

            Gauge.builder("druid.transactions.10_100ms", () -> transactionHistogram[2])
                    .description("事务执行耗时在10-100ms至间的数量")
                    .register(meterRegistry);

            Gauge.builder("druid.transactions.100_1000ms", () -> transactionHistogram[3])
                    .description("事务执行耗时在100-1000ms至间的数量")
                    .register(meterRegistry);

            Gauge.builder("druid.transactions.1000ms_plus", () -> transactionHistogram[4])
                    .description("事务执行耗时超过1000ms的数量")
                    .register(meterRegistry);
        }else {
            log.info("other db pool");
        }
    }
}
